package org.zjx.common.util;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class BeanUtil {

    /**
     * 对象属性拷贝（基础版）
     * @param source 源对象
     * @param targetClass 目标类
     * @return 拷贝后的新对象
     */
    public static <T> T copyProperties(Object source, Class<T> targetClass) {
        if (source == null) {
            return null;
        }

        try {
            T target = targetClass.getDeclaredConstructor().newInstance();
            // 获取源对象所有字段
            Field[] sourceFields = source.getClass().getDeclaredFields();

            for (Field sourceField : sourceFields) {
                sourceField.setAccessible(true);
                Object value = sourceField.get(source);

                try {
                    // 获取目标对象同名字段
                    Field targetField = targetClass.getDeclaredField(sourceField.getName());
                    targetField.setAccessible(true);

                    // 类型兼容性检查
                    if (targetField.getType().isAssignableFrom(sourceField.getType())) {
                        targetField.set(target, value);
                    }
                } catch (NoSuchFieldException ignored) {
                    // 忽略目标对象不存在的字段
                }
            }
            return target;
        } catch (Exception e) {
            throw new RuntimeException("对象属性拷贝失败", e);
        }
    }

    /**
     * 对象属性拷贝（增强版）
     * 将源对象中与目标对象同名的字段值复制到目标对象
     * @param source 源对象
     * @param target 目标对象（必须非null）
     * @throws IllegalArgumentException 当源对象或目标对象为null时抛出
     */
    public static void copyProperties(Object source, Object target) {
        if (source == null || target == null) {
            throw new IllegalArgumentException("Source and target objects must not be null");
        }

        Class<?> sourceClass = source.getClass();
        Class<?> targetClass = target.getClass();

        // 获取源对象所有字段
        Field[] sourceFields = sourceClass.getDeclaredFields();

        for (Field sourceField : sourceFields) {
            sourceField.setAccessible(true);
            Object value;
            try {
                value = sourceField.get(source);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Failed to get value from source field: " + sourceField.getName(), e);
            }

            try {
                // 在目标类中查找同名字段
                Field targetField = targetClass.getDeclaredField(sourceField.getName());
                targetField.setAccessible(true);

                // 类型兼容性检查（目标类型必须是源类型的超类型或相同类型）
                if (targetField.getType().isAssignableFrom(sourceField.getType())) {
                    try {
                        targetField.set(target, value);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException("Failed to set value to target field: " + targetField.getName(), e);
                    }
                }
            } catch (NoSuchFieldException ignored) {
                // 忽略目标对象不存在的字段
            }
        }
    }

    /**
     * 对象列表属性拷贝
     * @param sources 源对象列表
     * @param targetClass 目标类
     * @return 拷贝后的目标对象列表
     */
    public static <T, S> List<T> copyToList(List<S> sources, Class<T> targetClass) {
        if (sources == null || sources.isEmpty()) {
            return Collections.emptyList();
        }

        return sources.stream()
                .map(source -> copyProperties(source, targetClass))
                .collect(Collectors.toList());
    }
}